﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Windows.Forms;
using System.IO;
using System.Net;

namespace simpleDns
{
    public partial class mainForm : Form
    {
        private dnsServer dServer;
        private DataTable domainTable;
        private DOMAIN currentEdit;

        public mainForm()
        {
            InitializeComponent();
           
            rTabellist.Columns.Add("type", "type");
            rTabellist.Columns.Add("name", "name");
            rTabellist.Columns.Add("value", "value");
            rTabellist.Columns.Add("status", "status");
            rTabellist.Columns.Add("info", "info");
            rTabellist.Columns.Add("id", "id");
            rTabellist.Columns[5].Visible = false;

            dTablelist.Columns.Add("name", "name");
            dTablelist.Columns.Add("sort", "sort");
            dTablelist.Columns.Add("status", "status");
            dTablelist.Columns.Add("info", "info");
            dTablelist.Columns.Add("id", "id");
            dTablelist.Columns[4].Visible = false;
            
        }

        private void startService()
        {
            if (string.IsNullOrEmpty(settings.serverIp))
            {
                settings.log.add("server ip error");
                MessageBox.Show("监听IP错误，无法启动");
                return;
            }
            if (settings.udpNum == 0)
            {
                MessageBox.Show("UDP线程不能为0");
                return;
            }
            settings.log.add("service started");
            dServer.start();
            BTstopService.Enabled = true;
            BTstartService.Enabled = false;

        }
        private void stopService()
        {
            try
            {
                dServer.stop();
            }
            catch
            {

            }
            settings.log.add("stop service");
        }
        private void loadConfig()
        {
            if (String.IsNullOrEmpty(Properties.Settings.Default.dataPath))
            {
                Properties.Settings.Default.dataPath = Environment.CurrentDirectory + @"\data";
            }
            if (string.IsNullOrEmpty(Properties.Settings.Default.serverIp))
                Properties.Settings.Default.serverIp = GetAddressIP();
            if (string.IsNullOrEmpty(Properties.Settings.Default.dns1))
                Properties.Settings.Default.dns1 = "114.114.114.114";
            if (Properties.Settings.Default.udpNum == 0)
                Properties.Settings.Default.udpNum = 100;
            if (Properties.Settings.Default.serviceMode == 0)
                Properties.Settings.Default.serviceMode = 1;
            settings.dataPath = Properties.Settings.Default.dataPath;
            settings.ttl_default = Properties.Settings.Default.ttl_default;
            settings.dns1 = Properties.Settings.Default.dns1;
            settings.dns2 = Properties.Settings.Default.dns2;
            settings.serverIp = Properties.Settings.Default.serverIp;
            settings.cacheTrush = Properties.Settings.Default.cacheTrush;
            settings.udpNum = Properties.Settings.Default.udpNum;
            settings.tcpNum = Properties.Settings.Default.tcpNum;
            settings.autoHide = Properties.Settings.Default.autoHide;
            settings.autoRun = Properties.Settings.Default.autoRun;
            settings.autoStart = Properties.Settings.Default.autoStart;
            settings.serviceMode = Properties.Settings.Default.serviceMode;
            settings.log = new commonFunctions.asyncLog(Path.Combine(settings.dataPath, "logs"), 1000);
            dServer._dnsServers.Add(IPAddress.Parse(settings.dns1));
            if (!string.IsNullOrEmpty(settings.dns2))
                dServer._dnsServers.Add(IPAddress.Parse(settings.dns2));
            BTserviceMode.Text = ((ServiceMode)settings.serviceMode).ToString();
            settings.log.add("load config success");
        }
        private void loadData()
        {
            settings.log.add("start loading data");
            domainTable = new DataTable();
            settings.domains = new Dictionary<string, DOMAIN>();
            try
            {
                domainTable = new DataTable();
                settings.domains = new Dictionary<string, DOMAIN>();
                if (!Directory.Exists(settings.dataPath))
                    Directory.CreateDirectory(settings.dataPath);
                loadProcess lp = new loadProcess();
                lp.FormClosing += Lp_FormClosing;
                lp.ShowDialog();
            }
            catch
            {
                settings.log.add("error happens while data loading","load data error",commonFunctions.asyncLog.asyncLogLevel.ERROR);
            }
            settings.log.add("data loading success");
        }
        private void Lp_FormClosing(object sender, FormClosingEventArgs e)
        {
            domainTable = new DataTable();
            domainTable.Columns.Add(new DataColumn("domain"));
            domainTable.Columns.Add(new DataColumn("mode"));
            domainTable.Columns.Add(new DataColumn("status"));
            domainTable.Columns.Add(new DataColumn("info"));
            BTdomainList.DataSource = domainTable;
            foreach (DOMAIN kv in settings.domains.Values)
            {
                addDomain(kv, false);
            }
            BTdomainList.ClearSelection();
            settings.log.add("data load success");
        }
        private string GetAddressIP()
        {
            ///获取本地的IP地址
            string AddressIP = string.Empty;
            foreach (IPAddress _IPAddress in Dns.GetHostEntry(Dns.GetHostName()).AddressList)
            {
                if (_IPAddress.AddressFamily.ToString() == "InterNetwork")
                {
                    AddressIP = _IPAddress.ToString();
                }
            }
            return AddressIP;
        }

        #region private class

        private void changeMode(int i)
        {
            settings.serviceMode = i;
            Properties.Settings.Default.serviceMode = i;
            Properties.Settings.Default.Save();
            BTserviceMode.Text = ((ServiceMode)i).ToString();
            settings.log.add(BTserviceMode.Text, "change service mode");
        }
        private void BTromoteFirst_Click(object sender, EventArgs e)
        {
            changeMode(2);
            BTromoteFirst.Checked = true;
            BTromoteOnly.Checked = false;
            BTlocalFirst.Checked = false;
            BTlocalOnly.Checked = false;
        }

        private void BTlocalFirst_Click(object sender, EventArgs e)
        {
            changeMode(1);
            BTromoteFirst.Checked = false;
            BTromoteOnly.Checked = false;
            BTlocalFirst.Checked = true;
            BTlocalOnly.Checked = false;
        }

        private void BTromoteOnly_Click(object sender, EventArgs e)
        {
            changeMode(4);
            BTromoteFirst.Checked = false;
            BTromoteOnly.Checked = true;
            BTlocalFirst.Checked = false;
            BTlocalOnly.Checked = false;
        }

        private void BTlocalOnly_Click(object sender, EventArgs e)
        {
            changeMode(3);
            BTromoteFirst.Checked = false;
            BTromoteOnly.Checked = false;
            BTlocalFirst.Checked = false;
            BTlocalOnly.Checked = true;
        }
        #endregion

        #region main control
        private void BTstartService_Click(object sender, EventArgs e)
        {
            startService();
        }
        private void BTstopService_Click(object sender, EventArgs e)
        {
            stopService();
            BTstartService.Enabled = true;
            BTstopService.Enabled = false;
        }
        private void dataRefresh_Click(object sender, EventArgs e)
        {
            loadData();
        }
        private void openDataPath_Click(object sender, EventArgs e)
        {
            System.Diagnostics.Process.Start("explorer.exe", settings.dataPath);
        }
        private void BTconfigService_Click(object sender, EventArgs e)
        {
            systemConfig sc = new systemConfig();
            if (sc.ShowDialog() == DialogResult.OK)
            {
                loadConfig();
            }
        }

        private void notifyIcon1_MouseDoubleClick(object sender, MouseEventArgs e)
        {
            this.Visible = true;
            this.WindowState = FormWindowState.Normal;
        }
        private void mainForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            this.Visible = false;
            notifyIcon1.Visible = true;
            e.Cancel = true;
        }
        private void mainForm_Shown(object sender, EventArgs e)
        {
            dServer = new dnsServer();
            loadConfig();
            if (settings.autoRun)
            {
                loadData();
                startService();
            }
            if (settings.autoHide)
            {
                this.Visible = false;
                notifyIcon1.Visible = true;
            } 
        }
        private void 退出_Click(object sender, EventArgs e)
        {
            try
            {
                dServer.stop();
            }
            catch
            {

            }
            Environment.Exit(0);
        }
        #endregion

        #region domain edit
        private void BTdomainList_Click(object sender, EventArgs e)
        {
            if (BTdomainList.SelectedRows.Count == 1)
            {
                DataGridViewRow dr = BTdomainList.SelectedRows[0];
                string name = dr.Cells[0].Value.ToString();
                currentEdit = settings.domains[name];
                if (currentEdit.dnsMode)
                {
                    tabControl1.SelectedIndex = 1;
                }
                else
                {
                    tabControl1.SelectedIndex = 0;
                }
                rTabellist.Rows.Clear();
                foreach (ARECORD ar in currentEdit.aRecords.Values)
                {
                    addARECORDList(ar);
                }
                dTablelist.Rows.Clear();
                foreach (DNSRECORD ar in currentEdit.dnsRecords.Values)
                {
                    addDNSCORDList(ar);
                }
                dTablelist.ClearSelection();

                BTaddRecord.Enabled = true;
                BTenableRecord.Enabled = false;
                BTdisableRecord.Enabled = false;
                BTeditRecord.Enabled = false;
                BTdelRecord.Enabled = false;
                BTsearchRecord.Enabled = true;
                BTresetRecord.Enabled = false;

                BTeditDomain.Enabled = true;
                BTdelDomain.Enabled = true;
                BTenableDomain.Enabled = !currentEdit.enable;
                BTdisableDomain.Enabled = currentEdit.enable;
            }

        }

        private void BTaddDomain_Click(object sender, EventArgs e)
        {
            domainConfig dc = new domainConfig();
            dc.FormClosing += Dc_AddEnvent;
            dc.ShowDialog();
        }
        private void Dc_AddEnvent(object sender, FormClosingEventArgs e)
        {
            domainConfig dc = (domainConfig)sender;
            if (dc.DialogResult == DialogResult.OK)
            {
                try
                {
                    addDomain(dc.dm, true);
                }
                catch
                {

                }

            }
        }
        private void addDomain(DOMAIN dm, bool saveTofile)
        {
            try
            {
                if (!settings.domains.ContainsKey(dm.name) || !saveTofile)
                {
                    if (saveTofile)
                    {
                        dm.saveToFile();
                        settings.domains.Add(dm.name, dm);
                    }

                    dServer.setDomain(dm);
                    DataRow dr = domainTable.NewRow();
                    dr[0] = dm.name;
                    dr[1] = dm.dnsMode ? "DNS模式" : "解析模式";
                    dr[2] = dm.enable ? "激活" : "禁用";
                    dr[3] = dm.info;
                    domainTable.Rows.Add(dr);
                    domainTable.AcceptChanges();
                }
                else
                {
                    throw new Exception("域名已经存在:" + dm.name);
                }

            }
            catch (Exception ex)
            {
                throw ex;
            }

        }

        private void BTeditDomain_Click(object sender, EventArgs e)
        {
            if (BTdomainList.SelectedRows.Count == 1)
            {
                DataGridViewRow dr = BTdomainList.SelectedRows[0];
                DOMAIN dm = settings.domains[dr.Cells[0].Value.ToString()];
                domainConfig dc = new domainConfig(dm,dr.Index);
                dc.FormClosing += dc_EditEvent;
                dc.ShowDialog();
            }else
            {
                MessageBox.Show("请选择一个域名");
            }
        }
        private void dc_EditEvent(object sender, FormClosingEventArgs e)
        {
            domainConfig dc = (domainConfig)sender;
            if (dc.DialogResult == DialogResult.OK)
            {
                editDomain(dc.dm, dc.index);
            }
        }
        private void editDomain(DOMAIN dm, int index)
        {
            try
            {
                dm.saveToFile();
                dServer.setDomain(dm);
                settings.domains[dm.name] = dm;
                if (index != -1)
                {
                    DataRow dr = domainTable.Rows[index];
                    dr[0] = dm.name;
                    dr[1] = dm.dnsMode ? "DNS模式" : "解析模式";
                    dr[2] = dm.enable ? "激活" : "禁用";
                    dr[3] = dm.info;
                    domainTable.AcceptChanges();
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        private void BTdelDomain_Click(object sender, EventArgs e)
        {
            if (BTdomainList.SelectedRows.Count == 1)
            {
                DataGridViewRow dr = BTdomainList.SelectedRows[0];
                string dm = dr.Cells[0].Value.ToString();
                if(MessageBox.Show("确认删除",string.Format("确认删除域名 {0}", dm), MessageBoxButtons.YesNo) == DialogResult.Yes)
                {
                    delDomain(dm, dr.Index);
                }
            }
            else
            {
                MessageBox.Show("请选择一个域名");
            }
        }
        private void delDomain(string dm, int index)
        {
            try
            {
                dServer.delDomain(dm);
                domainTable.Rows.RemoveAt(index);
                domainTable.AcceptChanges();
                settings.domains.Remove(dm);
                File.Delete(string.Format(@"{0}\{1}.dns", settings.dataPath, dm));
            }
            catch
            {

            }

        }

        private void BTenableDomain_Click(object sender, EventArgs e)
        {
            if (BTdomainList.SelectedRows.Count == 1)
            {
                DataGridViewRow dr = BTdomainList.SelectedRows[0];
                DOMAIN dm = settings.domains[dr.Cells[0].Value.ToString()];
                dm.enable = true;
                editDomain(dm, dr.Index);
                BTenableDomain.Enabled = false;
                BTdisableDomain.Enabled = true;
            }
            else
            {
                MessageBox.Show("请选择一个域名");
            }
        }
        private void BTdisableDomain_Click(object sender, EventArgs e)
        {
            if (BTdomainList.SelectedRows.Count == 1)
            {
                DataGridViewRow dr = BTdomainList.SelectedRows[0];
                DOMAIN dm = settings.domains[dr.Cells[0].Value.ToString()];
                dm.enable = false;
                editDomain(dm, dr.Index);
                BTenableDomain.Enabled = true;
                BTdisableDomain.Enabled = false;
            }
            else
            {
                MessageBox.Show("请选择一个域名");
            }
        }
        #endregion

        #region record edit
        private void updateARECORDList()
        {
            foreach (DataGridViewRow rdr in rTabellist.Rows)
            {
                if (currentEdit.aRecords.ContainsKey(rdr.Cells[5].Value.ToString()))
                {
                    ARECORD ar = currentEdit.aRecords[rdr.Cells[5].Value.ToString()];
                    rdr.Cells[0].Value = ar.type.ToString();
                    rdr.Cells[1].Value = ar.name;
                    rdr.Cells[2].Value = ar.value;
                    rdr.Cells[3].Value = ar.enable ? "激活" : "禁用";
                    rdr.Cells[4].Value = ar.info;
                    rdr.Cells[5].Value = ar.id;
                }else
                {
                    rTabellist.Rows.Remove(rdr);
                }
                
            }
        }
        private void updateDRECORDList()
        {
            foreach (DataGridViewRow rdr in dTablelist.Rows)
            {
                if (currentEdit.dnsRecords.ContainsKey(rdr.Cells[4].Value.ToString()))
                {
                    DNSRECORD sr = currentEdit.dnsRecords[rdr.Cells[4].Value.ToString()];
                    rdr.Cells[0].Value = sr.name;
                    rdr.Cells[1].Value = sr.sort;
                    rdr.Cells[2].Value = sr.enable ? "激活" : "禁用";
                    rdr.Cells[3].Value = sr.info;
                    rdr.Cells[4].Value = sr.id;
                }else
                {
                    dTablelist.Rows.Remove(rdr);
                }
            }
        }
        private void addARECORDList(ARECORD ar)
        {
            DataGridViewRow rdr = new DataGridViewRow();
            rdr.CreateCells(rTabellist);
            rdr.Cells[0].Value = ar.type.ToString();
            rdr.Cells[1].Value = ar.name;
            rdr.Cells[2].Value = ar.value;
            rdr.Cells[3].Value = ar.enable ? "激活" : "禁用";
            rdr.Cells[4].Value = ar.info;
            rdr.Cells[5].Value = ar.id;
            rTabellist.Rows.Add(rdr);
        }
        private void addDNSCORDList(DNSRECORD sr)
        {
            DataGridViewRow rdr = new DataGridViewRow();
            rdr.CreateCells(dTablelist);
            rdr.Cells[0].Value = sr.name;
            rdr.Cells[1].Value = sr.sort;
            rdr.Cells[2].Value = sr.enable ? "激活" : "禁用";
            rdr.Cells[3].Value = sr.info;
            rdr.Cells[4].Value = sr.id;
            dTablelist.Rows.Add(rdr);
        }

        private void BTaddRecord_Click(object sender, EventArgs e)
        {
            if (tabControl1.SelectedIndex == 0)
            {
                recRecordConfig rc = new recRecordConfig();
                rc.FormClosing += rc_addEvent;
                rc.ShowDialog();
            }
            else
            {
                dnsRecordConfig dc = new dnsRecordConfig();
                dc.FormClosing += dc_addEnvent;
                dc.ShowDialog();
            }
        }
        private void dc_addEnvent(object sender, FormClosingEventArgs e)
        {
            dnsRecordConfig rec = (dnsRecordConfig)sender;
            if (rec.DialogResult == DialogResult.OK)
            {
                currentEdit.addDNSRecord(rec.rcd);
                editDomain(currentEdit,-1);
                addDNSCORDList(rec.rcd);
            }
        }
        private void rc_addEvent(object sender, FormClosingEventArgs e)
        {
            recRecordConfig rec = (recRecordConfig)sender;
            if (rec.DialogResult == DialogResult.OK)
            {
                currentEdit.addARecord(rec.rcd);
                editDomain(currentEdit, -1);
                addARECORDList(rec.rcd);
            }
        }

        private void BTeditRecord_Click(object sender, EventArgs e)
        {
            if (tabControl1.SelectedIndex==1)
            {
                if (dTablelist.SelectedRows.Count == 1)
                {
                    DataGridViewRow dr = dTablelist.SelectedRows[0];
                    dnsRecordConfig dc = new dnsRecordConfig(currentEdit.dnsRecords[dr.Cells[4].Value.ToString()]);
                    dc.FormClosing += dc_editEvent;
                    dc.ShowDialog();
                }else
                {
                    MessageBox.Show("请选择一个DNS记录");
                }
            }
            else{
                if (rTabellist.SelectedRows.Count == 1)
                {
                    DataGridViewRow dr = rTabellist.SelectedRows[0];
                    recRecordConfig rc = new recRecordConfig(currentEdit.aRecords[dr.Cells[5].Value.ToString()]);
                    rc.FormClosing += rc_editEvent;
                    rc.ShowDialog();
                }else
                {
                    MessageBox.Show("请选择一个解析记录");
                }
            }
        }
        private void rc_editEvent(object sender, FormClosingEventArgs e)
        {
            recRecordConfig rec = (recRecordConfig)sender;
            if (rec.DialogResult == DialogResult.OK)
            {
                currentEdit.editARecord(rec.rcd);
                editDomain(currentEdit, -1);
                updateARECORDList();
            }
        }
        private void dc_editEvent(object sender, FormClosingEventArgs e)
        {
            dnsRecordConfig rec = (dnsRecordConfig)sender;
            if (rec.DialogResult == DialogResult.OK)
            {
                currentEdit.editDNSRecord(rec.rcd);
                editDomain(currentEdit, -1);
                updateDRECORDList();
            }
        }

        private void BTdelRecord_Click(object sender, EventArgs e)
        {
            if (tabControl1.SelectedIndex == 1)
            {
                if (dTablelist.SelectedRows.Count == 1)
                {
                    DataGridViewRow dr = dTablelist.SelectedRows[0];
                    if (MessageBox.Show("确认删除", string.Format("确认删除记录 {0}", dr.Cells[0].Value), MessageBoxButtons.YesNo) == DialogResult.Yes)
                    {
                        currentEdit.delDNSRecord(dr.Cells[4].Value.ToString());
                        dTablelist.Rows.Remove(dr);
                        editDomain(currentEdit, -1);
                    }
                }
                else
                {
                    MessageBox.Show("请选择一个DNS记录");
                }
            }
            else
            {
                if (rTabellist.SelectedRows.Count == 1)
                {
                    DataGridViewRow dr = rTabellist.SelectedRows[0];
                    if (MessageBox.Show("确认删除", string.Format("确认删除记录 {0}", dr.Cells[0].Value), MessageBoxButtons.YesNo) == DialogResult.Yes)
                    {
                        currentEdit.delArecord(dr.Cells[5].Value.ToString());
                        rTabellist.Rows.Remove(dr);
                        editDomain(currentEdit,-1);
                    }
                }
                else
                {
                    MessageBox.Show("请选择一个解析记录");
                }
            }
        }

        private void BTenableRecord_Click(object sender, EventArgs e)
        {
            if (tabControl1.SelectedIndex == 1)
            {
                if (dTablelist.SelectedRows.Count == 1)
                {
                    DataGridViewRow dr = dTablelist.SelectedRows[0];
                    currentEdit.dnsRecords[dr.Cells[4].Value.ToString()].enable=true;
                    editDomain(currentEdit, -1);
                    updateDRECORDList();
                    BTenableRecord.Enabled = false;
                    BTdisableRecord.Enabled = true;      
                }
                else
                {
                    MessageBox.Show("请选择一个DNS记录");
                }
            }
            else
            {
                if (rTabellist.SelectedRows.Count == 1)
                {
                    DataGridViewRow dr = rTabellist.SelectedRows[0];
                    currentEdit.aRecords[dr.Cells[4].Value.ToString()].enable = true;
                    editDomain(currentEdit, -1);
                    updateARECORDList();
                    BTenableRecord.Enabled = false;
                    BTdisableRecord.Enabled = true;
                }
                else
                {
                    MessageBox.Show("请选择一个解析记录");
                }
            }
        }
        private void BTdisableRecord_Click(object sender, EventArgs e)
        {
            if (tabControl1.SelectedIndex == 0)
            {
                if (dTablelist.SelectedRows.Count == 1)
                {
                    DataGridViewRow dr = dTablelist.SelectedRows[0];
                    currentEdit.dnsRecords[dr.Cells[4].Value.ToString()].enable = false;
                    editDomain(currentEdit, -1);
                    updateDRECORDList();
                    BTenableRecord.Enabled = true;
                    BTdisableRecord.Enabled = false;
                }
                else
                {
                    MessageBox.Show("请选择一个DNS记录");
                }
            }
            else
            {
                if (rTabellist.SelectedRows.Count == 1)
                {
                    DataGridViewRow dr = rTabellist.SelectedRows[0];
                    currentEdit.aRecords[dr.Cells[4].Value.ToString()].enable = false;
                    editDomain(currentEdit, -1);
                    updateARECORDList();
                    BTenableRecord.Enabled = true;
                    BTdisableRecord.Enabled = false;
                }
                else
                {
                    MessageBox.Show("请选择一个解析记录");
                }
            }
        }

        private void rTabellist_MouseClick(object sender, MouseEventArgs e)
        {
            if (rTabellist.SelectedRows.Count == 1)
            {
                BTeditRecord.Enabled = true;
                BTdelRecord.Enabled = true;
                if (currentEdit.aRecords[rTabellist.SelectedRows[0].Cells[5].Value.ToString()].enable)
                {
                    BTenableRecord.Enabled = false;
                    BTdisableRecord.Enabled = true;
                }else
                {
                    BTenableRecord.Enabled = true;
                    BTdisableRecord.Enabled = false;
                }
                    
            }
        }
        private void dTablelist_CellMouseClick(object sender, DataGridViewCellMouseEventArgs e)
        {
            if (dTablelist.SelectedRows.Count == 1)
            {
                BTeditRecord.Enabled = true;
                BTdelRecord.Enabled = true;

                if (currentEdit.dnsRecords[dTablelist.SelectedRows[0].Cells[4].Value.ToString()].enable)
                {
                    BTenableRecord.Enabled = false;
                    BTdisableRecord.Enabled = true;
                }
                else
                {
                    BTenableRecord.Enabled = true;
                    BTdisableRecord.Enabled = false;
                }
            }
        }

        #endregion

        private void btDumpLogs_Click(object sender, EventArgs e)
        {
            settings.log.dump();
        }
    }
    
}
